
#include "Programme.h"
#include "Instruction.h"

// Constructeur

Programme::Programme(){

}

// Destructeur qui détruit les variables allouées dynamiquement

Programme::~Programme(){
	for(int i = 0; i < m_instructions.size(); ++i){
		delete m_instructions.at(i);
	}
}

// Ajouter des lignes de codeLobo qui seront analyser.

void Programme::addCodeLobo(string code) {
	m_codeLobo.push_back(code);
}

// Fonction qui permet d'analyser le codeLobo et qui va nous permettre de traduire le code en C++

void Programme::analyser() {

	//On va créer des instance de DefinitionFonction, Repete, DeclareFonction en fonction de ce qu'on va trouver
	//dans l'analyse du code LOBO
	std::stringstream ss;
	for(int i = 0; i < m_codeLobo.size(); ++i){
		ss << m_codeLobo.at(i)+" ";
	}
	std::string s;
	while(getline(ss, s, ' ')){
		if(s.compare("FONCTION")==0){
			std::string str = "FONCTION";
			while(s.compare("FIN_FONCTION")!=0){
				getline (ss, s, ' ');
				str+=" "+s;
			}

			str+=" FIN_FONCTION";

			m_instructions.push_back(new DefinitionFonction());
			m_instructions.at(m_instructions.size()-1)->addCodeLobo(str);
			m_instructions.at(m_instructions.size()-1)->analyser();

		}else if(s.compare("REPETE")==0){//REPETE


			std::string str = "REPETE";
			int repeteImbrique = 0;
			while(s.compare("FIN_REPETE")!=0 || repeteImbrique!=0){
				if(s.compare("FIN_REPETE")==0){
					--repeteImbrique;
				}
				getline (ss, s, ' ');
				if(s.compare("REPETE")==0){
					++repeteImbrique;
				}

				str+=" "+s;
			}

			str+=" FIN_REPETE";

			m_instructions.push_back(new Repete());
			m_instructions.at(m_instructions.size()-1)->addCodeLobo(str);
			m_instructions.at(m_instructions.size()-1)->analyser();

		}else if(s.compare("APPEL")==0){ // APPEL FONCTION

			getline (ss, s, ';');
			std::string str = "APPEL "+s+";";

			m_instructions.push_back(new AppelFonction());
			m_instructions.at(m_instructions.size()-1)->addCodeLobo(str);
			m_instructions.at(m_instructions.size()-1)->analyser();

		}else if(s.compare("DECLARE")==0){ // DECLARE VARIABLE
			getline (ss, s, ';');
			std::string str = "DECLARE "+s+";";

			m_instructions.push_back(new DeclareVariable());
			m_instructions.at(m_instructions.size()-1)->addCodeLobo(str);
			m_instructions.at(m_instructions.size()-1)->analyser();

		}else if(s.compare("AFFECTE")==0){ // AFFECTE VARIABLE
			getline (ss, s, ';');
			std::string str = "AFFECTE "+s+";";

			m_instructions.push_back(new AffecteVariable());
			m_instructions.at(m_instructions.size()-1)->addCodeLobo(str);
			m_instructions.at(m_instructions.size()-1)->analyser();

		}else if(s.compare("AFFICHE")==0){ // AFFICHE CHAINE
			getline (ss, s, ';');
			std::string str = "AFFICHE "+s+";";

			m_instructions.push_back(new AfficheChaine());
			m_instructions.at(m_instructions.size()-1)->addCodeLobo(str);
			m_instructions.at(m_instructions.size()-1)->analyser();

		}
	}
}

// Retourne un programme en C++, qui est la traduction du code Lobo.

std::string Programme::toString() const {

	string s = "#include <iostream>\nusing namespace std;\n\n";
	for(int i = 0 ; i < m_instructions.size() ; ++i){
		DefinitionFonction const * defFonction = dynamic_cast<DefinitionFonction const *>(m_instructions.at(i));
		if (defFonction != NULL){
			s+=m_instructions.at(i)->toString()+"\n";
		}
	}

	s+="int main(){ \n";
	for(int i = 0 ; i < m_instructions.size() ; ++i){
		DefinitionFonction const * defFonction2 = dynamic_cast<DefinitionFonction const *>(m_instructions.at(i));
		if (defFonction2 == NULL){
			s+=m_instructions.at(i)->toString()+"\n";
		}
	}
	s+="return 0; \n}";
	return s;
}

